package com.zm.admin.im;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.zm.admin.im.domain.ImChatRecord;
import com.zm.admin.im.dto.ImConst;
import com.zm.admin.im.dto.ImMappingDto;
import com.zm.admin.im.dto.ImMsgBody;
import com.zm.admin.im.dto.ImUser;
import com.zm.admin.im.service.ImChatRecordService;
import com.zm.admin.utils.ResultBean;
import com.zm.admin.ws.NioWebSocketChannelPool;
import com.zm.admin.ws.WsBean;
import com.zm.admin.zmeng.domain.ZmAttachment;
import com.zm.admin.zmeng.domain.ZmUser;
import com.zm.admin.zmeng.mapper.ZmUserMapper;
import com.zm.admin.zmeng.service.ZmAttachmentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/***
 *
 * @Auther: MuYun
 * @Date: 2023/2/2 16:31
 * @Description： 聊天室服务层
 *
 */
@Service
@Transactional()
@Slf4j
public class ImService {

    @Resource
    private NioWebSocketChannelPool socketChannelPool;

    @Resource
    private ZmUserMapper zmUserMapper;

    @Resource
    private ImChatRecordService imChatRecordService;

    @Resource
    private ZmAttachmentService zmAttachmentService;

    /**
     * 获取所有用户及相关记录
     * @return
     */
    public ResultBean online(){
        ResultBean resultBean=new ResultBean();
        try{
            //获取当前登录人id
            String loginId = StpUtil.getLoginIdAsString();
            //获取在线用户id集合
            Set<String> onlineIdList = socketChannelPool.getBindUserMap().keySet();
            List<ZmUser> zmUserList = zmUserMapper.selectList(null);
            //转换
            List<ImUser> imUserList = ImMappingDto.instance.toImUserList(zmUserList);
            //移除自身，不显示自己
            imUserList=imUserList.stream().filter(i->!loginId.equals(i.getId())).collect(Collectors.toList());
            /*--------------------开始组装每个imUser-------------------*/
            for(ImUser imUser:imUserList){
                //如果当前遍历的用户在/不在线，修改其状态
                if(onlineIdList.stream().anyMatch(i->i.equals(imUser.getId()))){
                    imUser.setUserStatus(ImConst.UserStatus.online);
                }else {
                    imUser.setUserStatus(ImConst.UserStatus.out);
                }
                //查询遍历的用户与当前用户相关的聊天记录
                List<ImChatRecord> chatRecordList=imChatRecordService.lambdaQuery().eq(ImChatRecord::getSendUserId,imUser.getId())
                        .eq(ImChatRecord::getReceiveUserId,loginId).orderByDesc(ImChatRecord::getId).list();
                imUser.setLastMsg("暂无消息");
                //log.info("聊天记录条数:{}",chatRecordList.size());
                if(chatRecordList.size()>0){
                    ImChatRecord imChatRecord = chatRecordList.get(0);
                    //设置当前用户与该用户(遍历的这个用户)最后一次发消息的时间
                    imUser.setLastSendTime(DateUtil.format(imChatRecord.getSendTime(),"HH:mm"));
                    ImMsgBody imMsgBody = JSON.parseObject(imChatRecord.getMsgBody(), ImMsgBody.class);
                    log.info("看看消息:{}",imMsgBody);
                    //设置当前用户与该用户(遍历的这个用户)最后一次发消息的内容（想一下qq的消息页
                    switch (imMsgBody.getMsgType()){
                        case text -> imUser.setLastMsg(imMsgBody.getContent());
                        case img -> imUser.setLastMsg("图片消息");
                    }
                    //设置当前用户与该用户的未读消息数量(过滤后统计总数转int
                    imUser.setNoReadNum((int)chatRecordList.stream().filter(i->!i.getReading()).count());
                }
            }
            /*-----------------------结束组装------------------------*/
            //该用户聊天上传的所有附件，接收/发送
            List<String> urlList = zmAttachmentService.lambdaQuery().eq(ZmAttachment::getCreateBy, loginId)
                    .eq(ZmAttachment::getType, "在线聊天")
                    .select(ZmAttachment::getUrlPath)
                    .orderByDesc(ZmAttachment::getId)
                    .list().stream().map(ZmAttachment::getUrlPath).collect(Collectors.toList());
            Map<String,Object> map=new HashMap<>();
            map.put("users",imUserList);
            map.put("urlList",urlList);
            resultBean.setCode(ResultBean.CODE_SUCCESS).setData(map);
        }catch (Exception e){
            log.error("获取消息接口报错:{}",e);
            resultBean.setCode(ResultBean.CODE_ERROR).setMsg("获取消息接口报错");
        }
        return resultBean;
    }

    /**
     * 获取聊天记录
     * @param userId 聊天对象
     * @return
     */
    public ResultBean userClick(String userId){
        ResultBean resultBean=new ResultBean();
        Map<String,Object> map=new HashMap<>();
        try{
            String loginId = StpUtil.getLoginIdAsString();
            //先查自己发的
            List<ImChatRecord> recordAllList = imChatRecordService.lambdaQuery().eq(ImChatRecord::getSendUserId, loginId)
                    .eq(ImChatRecord::getReceiveUserId, userId).list();
            //再加上自己接收的
            recordAllList.addAll(imChatRecordService.lambdaQuery().eq(ImChatRecord::getReceiveUserId, loginId)
                    .eq(ImChatRecord::getSendUserId, userId).list());
            //排序
            List<ImChatRecord> recordList = recordAllList.stream().sorted(Comparator.comparing(ImChatRecord::getId)).collect(Collectors.toList());
            //聊天记录中的图片url集合
            List<String> imgList=new ArrayList<>();
            //消息体集合
            List<ImMsgBody> msgList=new ArrayList<>();
            //组装返回数据
            for (ImChatRecord chatRecord:recordList){
                ImMsgBody imMsgBody = JSON.parseObject(chatRecord.getMsgBody(), ImMsgBody.class);
                //log.info("看看消息体:{}",imMsgBody);
                imMsgBody.setId(chatRecord.getId());
                //设置类型及格式对应的内容
                if(loginId.equals(chatRecord.getSendUserId())){
                    imMsgBody.setType(ImMsgBody.Type.self);
                }else{
                    imMsgBody.setType(ImMsgBody.Type.other);
                }
                if(ImMsgBody.MsgType.img.equals(imMsgBody.getMsgType())){
                    imgList.add(imMsgBody.getContent());
                }
                msgList.add(imMsgBody);
                //如果该条消息未读，修改状态
                if(!chatRecord.getReading()){
                    chatRecord.setReading(true);
                    imChatRecordService.updateById(chatRecord);
                }
            }
            map.put("imgList",imgList);
            map.put("msgList",msgList);
            resultBean.setCode(ResultBean.CODE_SUCCESS).setData(map);
        }catch (Exception e){
            log.error("获取与{}的聊天记录接口报错:{}",userId,e);
            resultBean.setCode(ResultBean.CODE_ERROR).setMsg("获取与的聊天记录接口报错");
        }
        return resultBean;
    }

    /**
     * 发送消息
     * @param userId 接收人（发给谁
     * @param content 消息内容
     * @param type 消息类型
     * @return
     */
    public ResultBean send(String userId,String content,ImMsgBody.MsgType type){
        ResultBean resultBean=new ResultBean();
        //log.info("看看参数{},{}",userId,content);
        try{
            //组装消息记录对象
            ImChatRecord chatRecord=new ImChatRecord();
            chatRecord.setSendTime(DateUtil.date());
            chatRecord.setSendUserId(StpUtil.getLoginIdAsString());
            chatRecord.setReceiveUserId(userId);
            ImMsgBody msgBody=new ImMsgBody();
            msgBody.setMsgType(type);
            msgBody.setId(chatRecord.getId());
            msgBody.setContent(content);
            chatRecord.setMsgBody(JSON.toJSONString(msgBody));
            if(StrUtil.isEmpty(userId)){
                return resultBean.setCode(ResultBean.CODE_ERROR).setMsg("未选择消息发送对象！");
            }
            //保存
            imChatRecordService.save(chatRecord);
            //向浏览器推送消息,发个响应就行，不用传数据
            //类似于和浏览器说声我发消息了，你接受下
            socketChannelPool.sendToUser(userId, WsBean.get(WsBean.CallBackEm.receive_msg));
            resultBean.setCode(ResultBean.CODE_SUCCESS).setData(msgBody);
        }catch (Exception e){
            log.error("发送消息接口报错:{}",e);
            resultBean.setCode(ResultBean.CODE_ERROR).setMsg("发送消息接口报错");
        }
        return resultBean;
    }

    /**
     * 发送新图片消息（即新上传的图片，非历史图片
     * @param request
     * @param file
     * @param userId
     * @return
     */
    public ResultBean sendNewImg(HttpServletRequest request,MultipartFile file, String userId){
        ResultBean resultBean=new ResultBean();
        try{
            String url = zmAttachmentService.upload(request, file, "在线聊天");
            ImChatRecord chatRecord=new ImChatRecord();
            chatRecord.setSendTime(DateUtil.date());
            chatRecord.setSendUserId(StpUtil.getLoginIdAsString());
            ImMsgBody msgBody=new ImMsgBody();
            msgBody.setContent(url);
            msgBody.setMsgType(ImMsgBody.MsgType.img);
            chatRecord.setMsgBody(JSON.toJSONString(msgBody));
            if(StrUtil.isEmpty(userId)){
                return resultBean.setCode(ResultBean.CODE_ERROR).setMsg("未选择消息发送对象！");
            }
            imChatRecordService.save(chatRecord);
            //向浏览器推送消息,发个响应就行，不用传数据
            //类似于和浏览器说声我发消息了，你接受下
            socketChannelPool.sendToUser(userId, WsBean.get(WsBean.CallBackEm.receive_msg));
            resultBean.setCode(ResultBean.CODE_SUCCESS).setData(msgBody);
        }catch (Exception e){
            log.error("发送新图片消息接口报错:{}",e);
            resultBean.setCode(ResultBean.CODE_ERROR).setMsg("发送图片消息接口报错");
        }
        return resultBean;
    }
}
